package character

import (
	"context"
	"encoding/json"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"github.com/rs/xid"
	"github.com/spf13/cast"
	"google.golang.org/grpc/metadata"
	"math/rand"
	"net/url"
	"reflect"
	"strings"
	"time"
)

const (
	UserAgent     = "User-Agent"
	DevicePc      = "pc"
	DevicePhone   = "phone"
	DeviceDefault = "default"
)

// NewRequestID 获取uuid
func NewRequestID() string {
	//guid := xid.New()
	return uuid.New().String()
}

// GetUid 获取uuid
func GetUid() string {
	return xid.New().String()
}

// GetRandom 获取指定范围随机数
func GetRandom(min, max int) int {
	if min == 0 && max == 0 {
		max = 100
	}
	if min > max {
		min, max = max, min
	}
	// 初始化随机数生成器
	rand.Seed(time.Now().UnixNano())
	// 生成一个[min, max]范围内的随机整数
	randomNumber := rand.Intn(max-min+1) + min
	return randomNumber
}

// IsURLEncoded 检查字符串是否包含URL编码的中文字符
func IsURLEncoded(s string) bool {
	// 简单检查是否包含%和中文常见编码模式
	// 中文字符UTF-8编码通常为 %E% 或 %xx%xx%xx 形式
	return strings.Contains(s, "%") &&
		(strings.Contains(s, "%E") ||
			strings.Contains(s, "%e") ||
			strings.Contains(s, "%2") ||
			strings.Contains(s, "%3"))
}

// DecodeIfEncoded 如果字符串是URL编码则解码
func DecodeIfEncoded(s string) string {
	if IsURLEncoded(s) {
		// 使用QueryUnescape解码查询参数形式的编码
		decoded, err := url.QueryUnescape(s)
		if err != nil {
			// 如果失败，尝试使用PathUnescape解码路径形式的编码
			decoded, err = url.PathUnescape(s)
			if err != nil {
				return s + err.Error()
			}
		}
		return decoded
	}
	return s
}

// ErrorReturn 返回错误
func ErrorReturn(ret, data any) []byte {
	da := map[string]interface{}{
		"ret":  ret,
		"data": data,
	}
	daString, _ := json.Marshal(da)
	return daString
}

// GetDeviceIdFromContext 从上下文中获取设备ID
func GetDeviceIdFromContext(ctx context.Context) string {
	var ua string
	if md, ok := metadata.FromIncomingContext(ctx); ok {
		if values := md.Get(UserAgent); len(values) > 0 {
			ua = strings.ToLower(values[0])
		}
	}
	if c, ok := ctx.(*gin.Context); ok {
		ua = c.Request.Header.Get(UserAgent)
	}
	ua = strings.ToLower(ua)
	// 移动设备关键字
	mobileKeywords := []string{
		"mobile", "android", "iphone", "ipod", "ipad",
		"windows phone", "blackberry", "opera mini", "iemobile", "iphone",
	}

	// 平板设备关键字
	tabletKeywords := []string{
		"tablet", "ipad", "kindle", "silk",
	}

	// 检查是否是平板
	for _, keyword := range tabletKeywords {
		if strings.Contains(ua, keyword) {
			return DeviceDefault
		}
	}

	// 检查是否是移动设备
	for _, keyword := range mobileKeywords {
		if strings.Contains(ua, keyword) {
			return DevicePhone
		}
	}

	return DevicePc
}

// ContainInterface ...
func ContainInterface(arr interface{}, str interface{}) bool {
	val := reflect.ValueOf(arr)
	if val.Kind() != reflect.Slice {
		return false
	}
	for i := 0; i < val.Len(); i++ {
		elem := val.Index(i)
		// 根据元素类型进行处理
		switch elem.Kind() {
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			if elem.Int() == cast.ToInt64(str) {
				return true
			}
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
			if elem.Uint() == cast.ToUint64(str) {
				return true
			}
		case reflect.Float32, reflect.Float64:
			if elem.Float() == cast.ToFloat64(str) {
				return true
			}
		case reflect.String:
			if elem.String() == cast.ToString(str) {
				return true
			}
		case reflect.Bool:
			if elem.Bool() == cast.ToBool(str) {
				return true
			}
		default:
			if elem.Interface() == str {
				return true
			}
		}
	}
	return false
}

// ContainString 检查字符串数组中是否包含指定的字符串
func ContainString(arr []string, str string) bool {
	for _, value := range arr {
		if value == str {
			return true // 找到了，返回true
		}
	}
	return false // 遍历完数组都没有找到，返回false
}

// ContainInt32 检查字符串数组中是否包含指定的字符串
func ContainInt32(arr []int32, str int32) bool {
	for _, value := range arr {
		if value == str {
			return true // 找到了，返回true
		}
	}
	return false // 遍历完数组都没有找到，返回false
}

// ContainInt64 检查字符串数组中是否包含指定的字符串
func ContainInt64(arr []int64, str int64) bool {
	for _, value := range arr {
		if value == str {
			return true // 找到了，返回true
		}
	}
	return false // 遍历完数组都没有找到，返回false
}

// ContainFloat64 检查字符串数组中是否包含指定的字符串
func ContainFloat64(arr []float64, str float64) bool {
	for _, value := range arr {
		if value == str {
			return true // 找到了，返回true
		}
	}
	return false // 遍历完数组都没有找到，返回false
}
